package com.example.demo.filter;

import java.net.URI;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import com.example.demo.predicate.ReadBodyRoutePredicateFactory;
import com.example.demo.util.ConverterUtil;
import com.example.demo.util.MD5Util;
import com.google.common.collect.Lists;
import com.google.gson.Gson;


/**
 * 接口签名验证
 * @author 88377761
 *
 */
@Component
public class SignGatewayFilterFactory extends AbstractGatewayFilterFactory<SignGatewayFilterFactory.Config> {
	private static final Logger LOGGER = LoggerFactory.getLogger(SignGatewayFilterFactory.class);

	public SignGatewayFilterFactory() {
		super(Config.class);
	}


	public static class Config {
		// 控制是否开启认证
		private List<String> passUrl=Lists.newArrayList();

		public List<String> getPassUrl() {
			return passUrl;
		}

		public void setPassUrl(List<String> passUrl) {
			this.passUrl = passUrl;
		}

	}

	private String toJsonStr(String args) {
		if(StringUtils.isBlank(args)) {
			return "{}";
		}
		Map<String, Object> collect = Arrays.stream(args.split("&"))
                .map(str -> str.split("="))
                .collect(Collectors.toMap(x -> x[0], x -> x[1],
                        (u, v) -> {
                            throw new IllegalStateException(String.format("Duplicate key %s", u));
                        },LinkedHashMap::new));
		return new Gson().toJson(collect);
	}
	/**
	 * @param config
	 * @return create by zy 88377761
	 */
	@Override
	public GatewayFilter apply(Config config) {
		return (exchange, chain) -> {
			URI uri = exchange.getRequest().getURI();
			String path = uri.getPath();
			AntPathMatcher matcher = new AntPathMatcher();
			for(String pattern:config.passUrl) {
				if(matcher.match(pattern,path))
					return chain.filter(exchange);
			}
			ServerHttpRequest request = exchange.getRequest();
			ServerHttpResponse response = exchange.getResponse();
			String sign = request.getHeaders().getFirst("sign");
			if (StringUtils.isBlank(sign)) {
				response.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
				return response.setComplete();
			}
			try {
				HttpMethod method=request.getMethod();
				if(method==HttpMethod.GET) {
					String plaintext=toJsonStr(uri.getRawQuery());
					String md5=MD5Util.getMD5(plaintext);
					if (!sign.equals(md5)) {
						response.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
						return response.setComplete();
					}
					return chain.filter(exchange);
				}
				if(method==HttpMethod.POST) {
					Object cachedRequestBodyObject = exchange.getAttributeOrDefault(ReadBodyRoutePredicateFactory.CACHE_REQUEST_BODY_OBJECT_KEY, null);
					String md5=MD5Util.getMD5(ConverterUtil.toString(cachedRequestBodyObject));
					if (!sign.equals(md5)) {
						response.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
						return response.setComplete();
					}
					return chain.filter(exchange);
				}
			} catch (Exception e) {
				LOGGER.error("校验sign:", e);
				response.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
				return response.setComplete();
			}
			return chain.filter(exchange);
		};
	}
	
}


